package connexionServer;
//******************************************************************************
// Connexion.java
// E.Lefran�ois 8 f�vrier 2001
// Projet "Chat"
//******************************************************************************
import java.lang.Thread;
import java.io.*;
import java.net.*;
import java.util.*;

import sheepmixView.client.model.Musique;


//==============================================================================
// Objet concurrent, responsable de la connexion avec le client
// Cet objet a un acces direct a la liste des connexions maintenue par l'objet
// "Serveur" (acces en exclusion mutuelle)
//==============================================================================

class Connexion extends Thread implements Observer {

	// Variables d'instance

	private Socket a_socketClient; 	// socket connectee au client

	//private Vector<Connexion> a_listeDesConnexions;   // Liste des connexions avec les clients

	private ControleurConnexions a_leControleurDesConnexions;
	// Pour controler si la connexion
	// devient inactive

	private boolean clientActif;   // "true" tant que le client n'a pas
	// demande une fermeture de la ssession
	private String imeiClient;       // Identificateur du client (IMEI)

	//private BufferedReader canalDentree;
	private ObjectInputStream canalDentree;
	// Canal d'entree avec le client (texte)

	//private PrintWriter canalDeSortie;
	private ObjectOutputStream canalDeSortie;
	// Canal de sortie avec le client (Texte)

	//private ObjectOutputStream out;
	// Canal de sortie pour les listes


	//private DataOutputStream outputDataCanal;
	// Canal de sortie pour donnees uniquement:  non utilise !!
	// Pour le creer eventuellement:
	// outputDataCanal = new DataOutputStream (clientSocket.getOutputStream());

	// Constructeur
	public Connexion (	Socket socketClientAssociee,
			ControleurConnexions controleurAssocie,
			Vector<Connexion> listeDesConnexions) {

		System.out.println (">> Nouvelle connexion ..");
		a_socketClient = socketClientAssociee;
		a_leControleurDesConnexions = controleurAssocie;
		//a_listeDesConnexions = listeDesConnexions;
		clientActif = true;
		ControleurConnexions.jukeBox.addObserver(this);

		try {
			canalDentree = new ObjectInputStream(a_socketClient.getInputStream());
			canalDeSortie = new ObjectOutputStream
					(a_socketClient.getOutputStream());
			//out = new ObjectOutputStream(a_socketClient.getOutputStream());
		}
		catch (IOException e) {
			fermerConnexion();
			return;
		}
		this.start();	// Demarrer l'activite
	}

	public String getImei() {
		return imeiClient;
	}

	// Activite concurrente
	public void run() {
		String ligneDeTexte;  // Texte envoye par le client

		// Boucle d'attente
		try {
			while (clientActif) {
				ligneDeTexte = (String)canalDentree.readObject();
				System.out.println (ligneDeTexte);

				analyserLigneRecue(ligneDeTexte);
			}
		}
		catch (IOException e) {} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			fermerConnexion();
		}
	}


	// Methodes privees
	private void analyserLigneRecue (String ligne) {
		StringTokenizer st = new StringTokenizer (ligne, "#");
		try {
			String commande = st.nextToken();

			if (commande.equals("CTR")){
				String retour = st.nextToken();
				if (retour.equals("LOGIN")) {
					this.imeiClient = st.nextToken();
					envoyerTexteAuClient("#CTR#LOGIN_OK");
					a_leControleurDesConnexions.getCredit(this.imeiClient);
				}
				else if (retour.equals("LOGOUT")) {
					clientActif = false;
				}
				else if (retour.equals("CREDIT")) {
					envoyerTexteAuClient("#CTR#CREDIT#"+a_leControleurDesConnexions.getCredit(this.imeiClient));
				}
				else if (retour.equals("START")) {
					System.out.println("Got Start from GUI !");
					a_leControleurDesConnexions.playPlaylist();
				}
				else if (retour.equals("STOP")) {
					System.out.println("Got Stop from GUI !");
					a_leControleurDesConnexions.stopPlaylist();
				}
				else if (retour.equals("PASS")) {
					System.out.println("Got Pass from GUI !");
					a_leControleurDesConnexions.pass();
					envoyerTexteAuClient("#CTR#TRANS OK");
				}
				else if (retour.equals("LOAD_GENRE")) {
					LinkedList<String> playlist = new LinkedList<String>();
					System.out.println("Load genre server side");
					a_leControleurDesConnexions.flushPlaylist();
					while (st.hasMoreTokens()) {
						String genre = st.nextToken();
						playlist.add(genre);
					}
					a_leControleurDesConnexions.addPlaylist(playlist);
					envoyerMusiquesAuClient(a_leControleurDesConnexions.getCurrentPlaylist());
				}
				else if (retour.equals("LOAD")) {
					System.out.println("Got Load from GUI !");
					// Attendre un tableau de genre.
					a_leControleurDesConnexions.load();
				}
				else if (retour.equals("UPVOLUME")) {
					// TODO
				}
				else if (retour.equals("DOWNVOLUME")) {
					// TODO
				}
				else erreurDeDonnees(ligne);
			}
			else if (commande.equals("GET")){
				String retour = st.nextToken();
				if (retour.equals("ARTISTE")) {
					if(st.hasMoreTokens()) {
						String genre = st.nextToken();
						LinkedList<String> artists = a_leControleurDesConnexions.getArtist(genre);
						envoyerTexteAuClient("#CTR#LSTRING#ARTISTES");
						envoyerListeningAuClient(artists);
						//broadcast("#DATA#SheepMix#Voici la liste des artistes pour le genre : " + genre);
						System.out.println("=============ARTIST===========");
						System.out.println(artists);
					}
					else {
						LinkedList<String> artists = a_leControleurDesConnexions.getArtist();
						envoyerTexteAuClient("#CTR#LSTRING#ARTISTES");
						envoyerListeningAuClient(artists);
						//broadcast("#DATA#SheepMix#Voici la liste des artistes presents dans la base");
						System.out.println("=============ARTIST (ALL)===========");
						System.out.println(artists);
					}
				}
				else if (retour.equals("GENRE")) {
					LinkedList<String> genres = a_leControleurDesConnexions.getGenre();
					envoyerTexteAuClient("#CTR#LSTRING#GENRES");
					envoyerListeningAuClient(genres);
					System.out.println("=============GENRES===========");
					System.out.println(genres);
					//broadcast("#DATA#SheepMix#Voici la liste des genres present dans la base");
				}
				else if (retour.equals("TRACKS")) {
					String artiste = st.nextToken();
					LinkedList<Musique> musiques = a_leControleurDesConnexions.getTracks(artiste);
					envoyerTexteAuClient("#CTR#LMUSIQUE");
					envoyerMusiquesAuClient(musiques);
					//broadcast("#DATA#SheepMix#Voici les morceaux de : " + artiste);
					System.out.println("=============TRACKS===========");
					System.out.println(musiques);
				}
				else if (retour.equals("CURRENT_MUSIC")) {
					System.out.println("CURRENT_MUSIC");
					System.out.println(a_leControleurDesConnexions.getPlayedMusic());
					envoyerMusiqueAuClient(a_leControleurDesConnexions.getPlayedMusic());
				}
				else if (retour.equals("CURRENT_PLAYLIST")) {
					System.out.println("CURRENT_PLAYLIST");
					envoyerMusiquesAuClient(a_leControleurDesConnexions.getCurrentPlaylist());
				}
			}
			else if (commande.equals("POST")) {
				String id = st.nextToken();
				if (a_leControleurDesConnexions.getCredit(this.imeiClient) > 0) {
					if(a_leControleurDesConnexions.addMusic(Integer.valueOf(id))) {
						
						a_leControleurDesConnexions.decrementerCredit(this.imeiClient);
						envoyerTexteAuClient("#CTR#POST_OK");
						System.out.println("Demande d'un musique id = " + Integer.valueOf(id));
						a_leControleurDesConnexions.envoyerUpdateMusiqueGUI(a_leControleurDesConnexions.getCurrentPlaylist());
					}
					else {
						envoyerTexteAuClient("#CTR#ALREADY_EXISTS");
					}
					
				}
				else {
					envoyerTexteAuClient("#CTR#POST_FAIL");
				}	
			}
			else erreurDeDonnees(ligne);
		}
		catch (Exception e) {erreurDeDonnees(ligne);}
	}

	/*private void broadcast(String texte) throws IOException {
		// Envoyer le message a chaque client
		Connexion uneConnexion;
		synchronized (a_listeDesConnexions) {
			for (   Enumeration<Connexion> en =
					a_listeDesConnexions.elements();
					en.hasMoreElements();) {
				uneConnexion = en.nextElement();
				synchronized (uneConnexion) {
					canalDeSortie.writeObject(texte);
					canalDeSortie.flush();
				}
			}
		}
	}*/

	private synchronized void envoyerTexteAuClient (String texte) throws IOException {
		System.out.println("Envoi : "+ texte);
		canalDeSortie.writeObject(texte);
		canalDeSortie.flush();
	}

	public synchronized void envoyerMusiquesAuClient (LinkedList<Musique> l) {
		try {
			System.out.println("Envoi musique : " + l.getFirst().getAuteur() + " - " + this.imeiClient);
			canalDeSortie.writeObject(l);
			canalDeSortie.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private synchronized void envoyerMusiqueAuClient (Musique m) {
		try {
			canalDeSortie.writeObject(m);
			canalDeSortie.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private synchronized void envoyerListeningAuClient (LinkedList<String> l) {
		try {
			canalDeSortie.writeObject(l);
			canalDeSortie.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void erreurDeDonnees (String ligneRecue) {
		fermerConnexion();
	}

	private void fermerConnexion() {
		try {
			a_socketClient.close();
		}
		catch (IOException e) {}

		synchronized (a_leControleurDesConnexions) {
			a_leControleurDesConnexions.finDeConnexion(this);
			// Le signaler au controleur des connexions
		}
	}


	@Override
	public void update(Observable arg0, Object arg1) {
		if (imeiClient.equals("sheepGUI")) {
			System.out.println("Update pour la GUI");
			envoyerMusiqueAuClient(a_leControleurDesConnexions.getPlayedMusic());
			envoyerMusiquesAuClient(a_leControleurDesConnexions.getCurrentPlaylist());
		}

	}

}

